﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Configuration;

namespace Colonisator.Classes
{
    /// <summary>
    /// Définit une partie de Colonisator
    /// </summary>
    [Serializable()]
    public class Partie
    {
        /// <summary>
        /// Liste des joueurs de la partie (humains, IA, factions IA)
        /// </summary>
        public List<Joueur> JoueursPartie { get; set; }

        /// <summary>
        /// Représente le plateau (pas d'aspect graphique)
        /// </summary>
        public Plateau PlateauPartie { get; set; }

        /// <summary>
        /// Liste des tours. Permet l'historisation
        /// </summary>
        public List<Tour> ToursPartie { get; set; }

        /// <summary>
        /// Représente l'économie d'ensemble de la partie
        /// </summary>
        public Economie EconomiePartie { get; set; }

        /// <summary>
        /// Donne le classement des joueurs
        /// </summary>
        public Classement ClassementPartie { get; set; }

        /// <summary>
        /// Le contenu du pool de cartes
        /// </summary>
        public List<Carte> ListeCartes { get; set; }

        /// <summary>
        /// Donne le tour en cours
        /// </summary>
        public Tour TourEnCours
        {
            get
            {
                return this.ToursPartie.Find(x => x.EstTourCourant);
            }
        }
        /// <summary>
        /// Pour les traces debug
        /// </summary>
        public bool ModeDebug { get; set; }

        /// <summary>
        /// Utilisé lors du ModeDebug pour insérer dans les logs
        /// </summary>
        public Logger Log { get; private set; }

        private static Partie _partie;
        public static Partie GetInstance()
        {
            if (_partie == null)
            {
                _partie = new Partie();
            }
            return _partie;
        }

        /// <summary>
        /// Constructeur par défaut
        /// </summary>
        public Partie()
        {
            JoueursPartie = new List<Joueur>();
            PlateauPartie = new Plateau();
            ToursPartie = new List<Tour>();
            EconomiePartie = new Economie();
            ListeCartes = new List<Carte>();

            Log = new Logger();
        }

        public void CreerPartie()
        {          

            // Création de navires
            var navireCUII = new Navire() { ID = 1, Nom = "Le Poséïdon", Table = new TableDeBord(), Rang = RangNavire.Rang1 };
            var navireCUII2 = new Navire() { ID = 2, Nom = "Le Respectueux", Table = new TableDeBord(), Rang = RangNavire.Rang1 };

            var navireCPL = new Navire() { ID = 1, Nom = "Le Pourceau", Table = new TableDeBord(), Rang = RangNavire.Rang4 };
            var navireCPL2 = new Navire() { ID = 2, Nom = "Le Banni", Table = new TableDeBord(), Rang = RangNavire.Rang4 };
            var navireCPL3 = new Navire() { ID = 3, Nom = "Le Brutal", Table = new TableDeBord(), Rang = RangNavire.Rang4 };

            var navireCMR = new Navire() { ID = 1, Nom = "La Poule", Table = new TableDeBord(), Rang = RangNavire.Rang5 };

            var patrouilleurPiofo = new Navire() { ID = 2, Nom = "Le Goêlier", Table = new TableDeBord(), Rang = RangNavire.Rang6 };

            var navireH = new Navire() { ID = 1, Nom = "", Table = new TableDeBord(), Rang = RangNavire.Rang4 };
            var navireIA = new Navire() { ID = 1, Nom = "", Table = new TableDeBord(), Rang = RangNavire.Rang4 };

            // Création des joueurs
            var joueurHumain = new JoueurHumain(PlayerConfiguration.GetInstance().PlayerProfilesList.PlayerProfile.Find(x => x.ActiveProfile));
            joueurHumain.Navires = new List<Navire>() { { navireH } };
                
            var joueurIA = new JoueurIA
            {
                NomJoueur = "IA",
                CouleurJoueur = Color.RoyalBlue, 
                Navires = new List<Navire>() { { navireIA } }
            };

            // Factions
            var cuii = new CUII
            {
                Navires = new List<Navire>() { { navireCUII }, { navireCUII2 } }
            };

            var cpl = new CPL
            {
                Navires = new List<Navire>() { { navireCPL }, { navireCPL2 }, { navireCPL3 } }
            };

            var cmr = new CMR
            {
                Navires = new List<Navire>() { { navireCMR } }
            };

            var piofo = new PenitencierPiofo
            {
                Navires = new List<Navire>() { { patrouilleurPiofo } }
            };                

            // Création des îles
            PlateauPartie.Cases.Add(new Sundercity());
            PlateauPartie.Cases.Add(new IleNeutre1());

            // Détermination des propriétaires
            List<Ile> listeIles = this.DonnerIles();

            cuii.Proprietes.Add(listeIles.Find(x => x.NomIle == "Ile Neutre 1"));
            cuii.Proprietes.Add(listeIles.Find(x => x.NomIle == "Ile Neutre 2"));
            cuii.Proprietes.Add(listeIles.Find(x => x.NomIle == "Ile Neutre 3"));

            piofo.Proprietes.Add(listeIles.Find(x => x.NomIle == "Pénitencier de Piofo"));

            // Alimentation Partie
            var partie = Partie.GetInstance();

            partie.JoueursPartie = new List<Joueur>() { { cuii }, { cpl }, { cmr }, { piofo }, { joueurHumain }, { joueurIA } };

        }        

        /// <summary>
        /// Sérialise l'objet Partie en cours, comprenant toutes les instances associées.
        /// Liste des valeurs de retour : 
        ///  -> 0 : la sauvegarde s'est effectuée correctement
        ///  -> 1 : problème lors de la sauvegarde
        /// </summary>
        /// <returns></returns>
        public Int32 SauverPartie()
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(Partie));
                StreamWriter fichier = new StreamWriter(Constantes.SAUVEGARDE_PARTIE + "/test.xml");
                serializer.Serialize(fichier, this);
                fichier.Close();
            }
            catch
            {
                return Constantes.CODE_RETOUR_KO;
            }

            return Constantes.CODE_RETOUR_OK;
        }

        /// <summary>
        /// Retourne une Partie chargée.
        /// </summary>
        /// <returns></returns>
        public Partie ChargerPartie()
        {
            Partie lPartieChargee = new Partie();


            //overview = (Book)reader.Deserialize(file);

            return lPartieChargee;
        }

        #region Utilitaires

        /// <summary>
        /// retourne la liste des îles
        /// </summary>
        /// <returns></returns>
        public List<Ile> DonnerIles()
        {
            return this.PlateauPartie.Cases.Where(x => typeof(Ile).IsAssignableFrom(x.GetType())).Cast<Ile>().ToList();
        }

        /// <summary>
        /// retourne l'instance de l'île, selon son type
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T DonnerIle<T>() where T : Ile
        {
            return (T)this.PlateauPartie.Cases.Where(x => x.GetType().IsAssignableFrom(typeof(T))).First();
        }

        /// <summary>
        /// retourne l'instance de l'île, selon son nom
        /// </summary>
        /// <param name="nomIle"></param>
        /// <returns></returns>
        public Ile DonnerIle(string nomIle)
        {
            return DonnerIles().Where(x => x.NomIle.Equals(nomIle)).First();
        }

        /// <summary>
        /// retourne le tour courant
        /// </summary>
        /// <returns></returns>
        public Tour DonnerTourCourant()
        {
            return _partie.ToursPartie.Where(x => x.EstTourCourant).First();
        }

        #endregion
    }
}
